home *** CD-ROM | disk | FTP | other *** search
- /*
- * --- SHAR_CMD.C ---
- * --- Command Portion of ---
- * --- UNSHAR.C ---
- *
- * --- Copywrite 24 September, 1986 ---
- * --- John Birchfield ---
- * --- 411 Crane Ave. ---
- * --- Turlock, CA 95380 ---
- * --- (209) 634-6243 ---
- *
- * Program to decode files created by the shell archive { shar }
- * utility on Un*x machines or pc's. Current capabilities include
- *
- * 1. Able to unshar into a user specified directory or subdirectory
- * as specified by a command line option { -Ddirectory_name }
- *
- * 2. Recognizes the following commands
- * cat, sed, uudecode, mkdir, chdir,
- * {test -f, test -d, test <number -ne wc ... }
- *
- * 3. Can handle shar scripts created with the
- * Options { -a -v -p -b -c -d }
- *
- * 4. Successfully traverses directories and sub-directories
- * creating the necessary subdirectories as necessary.
- *
- * CAVEATS:
- * Word Counting between Un*x machines and pc's just isn't
- * gonna work out too well. The \r\n - \n thing is not
- * an easy thing to work around - and to be quite frank
- * I just ain't up to it.
- *
- * Program written for the Desmet (C-Ware) C Compiler Version 2.61
- * not all of the routines in DOS_C.C and DOS_A.A are used by this
- * program. The program consists of the following modules:
- * UNSHAR.C
- * SHAR_CMD.C
- * DOS_C.C
- * DOS_A.A
- *
- * This program is hereby placed in the public domain for
- * non-commersial use.
- *
- */
-
- # include <stdio.h>
- # include "unshar.h"
- # include "dos.h"
-
-
-
-
- /*
- * P_ERROR () - p_error () is a simple routine for
- * displaying a message consisting of a sequence of
- * strings thru stdout. The first parameter is an
- * integer { if non-zero an exit occurs } the last
- * parameter is an empty string.
- */
-
- void p_error (no, args)
- int no;
- char *args;
- {
- char **tmp;
- tmp = &args;
- while (**tmp)
- fputs (*tmp++, stdout);
- if (no)
- _exit (no);
- }
-
-
-
-
- /*
- * DO_CD () - change directories
- */
-
- int do_cd (fp)
- FILE *fp;
- {
- char buf [20];
- get_tok (buf, fp);
- return (chdir (buf));
- }
-
-
-
-
- /*
- * DO_MKDIR () - make a directory
- */
-
- int do_mkdir (fp)
- FILE *fp;
- {
- char buf [20];
- get_tok (buf, fp);
- return (mkdir (buf));
- }
-
-
-
-
- /*
- * DO_EXIT () - Bye Bye
- */
-
- void do_exit (fp)
- FILE *fp;
- {
- char buf [20];
- get_tok (buf, fp);
- exit (atoi (buf));
- }
-
-
-
-
- /*
- * DO_CAT () - get the destination filename, get the
- * terminating string open the file and pass the contents
- * of the input stream to it until the termination flag
- * is recognized.
- */
-
- void do_cat (fp)
- FILE *fp;
- {
- FILE *f_out;
- char delimiter [80], fname [65], *dp,
- buf [256],
- tmp [15];
- int len;
-
- fname [0] = delimiter [0] = '\0';
- do {
- get_tok (tmp, fp);
- if (strncmp (tmp, "<<", 2)==0)
- get_tok (delimiter, fp);
- else if (strncmp (tmp, ">", 1)==0)
- get_tok (fname, fp);
- } while (fname [0]=='\0' || delimiter [0]=='\0');
-
- fix_file_name (fname);
- if ((f_out=creat (fname))==-1)
- p_error (1, "Cat Can't Create '", fname, "'\n", "");
- dp = &delimiter [1];
- len = strlen (dp);
- while (fgets (buf, 256, fp)) {
- if (strncmp (dp, buf, len)==0)
- break;
- fputs (buf, f_out);
- }
- fclose (f_out);
- }
-
-
-
-
- /*
- * DO_SED () - do_sed () works just like do_cat ()
- * except that the command line has the sed s/ //
- * translation parameter in it { one more token }
- * Command lines are of the form
- * sed 's/^ X//' << \SHAR_EOF > '.cshrc'
- */
-
- void do_sed (fp)
- FILE *fp;
- {
- FILE *f_out;
- char replace [40], delimiter [80], fname [65], *dp, *rp,
- buf [256], *nbuf,
- tmp [15];
- int len, rlen;
-
- get_tok (replace, fp);
- fname [0] = delimiter [0] = '\0';
- do {
- get_tok (tmp, fp);
- if (strncmp (tmp, "<<", 2)==0)
- get_tok (delimiter, fp);
- else if (strncmp (tmp, ">", 1)==0)
- get_tok (fname, fp);
- } while (fname [0]=='\0' || delimiter [0]=='\0');
-
- fix_file_name (fname);
- rp = &replace [3];
- if (index (rp, '/'))
- *index (rp, '/') = '\0';
- rlen = strlen (rp);
- nbuf = &buf [0] + rlen;
- if ((f_out=creat (fname))==-1)
- p_error (1, "Cat Can't Create '", fname, "'\n", "");
- dp = &delimiter [1];
- len = strlen (dp);
- while (fgets (buf, 256, fp)) {
- if (strncmp (dp, buf, len)==0)
- break;
- if (strncmp (rp, buf, rlen)==0)
- fputs (nbuf, f_out);
- else
- fputs (buf, f_out);
- }
- fclose (f_out);
- ;
- }
-
-
-
- /*
- * DO_UUDECODE () - do_uudecode () handles uudecoding
- * chores in the same way that do_cat () and do_sed ()
- * process their input. There are differnces in that
- * the uuencoded stream has it's filename as the
- * beginning of the file and not imbedded in
- * the uudecode command line.
- */
-
- void do_uudecode (fp)
- FILE *fp;
- {
- FILE *f_out;
- char delimiter [80], fname [65], *dp,
- buf [256];
- int len;
-
- do {
- get_tok (delimiter, fp);
- } while (strncmp (delimiter, "<<", 2));
-
- get_tok (delimiter, fp);
- dp = &delimiter [1];
- len = strlen (dp);
- fname [0] = '\0';
- do {
- if (get_tok (fname, fp)==0)
- p_error (2, "Uudecode: No begin statement\n", "");
- } while (strcmp (fname, "begin"));
- get_tok (fname, fp);
- get_tok (fname, fp);
- fix_file_name (fname);
- if ((f_out=creat (fname))==-1)
- p_error (1, "Uudecode Can't Create '", fname, "'\n", "");
-
- decode(fp, f_out);
-
- if (fgets(buf, sizeof buf, fp) == NULL || strcmp(buf, "end\n"))
- p_error (5, "Uudecode No end line\n", "");
- while (fgets (buf, sizeof (buf), fp))
- if (strncmp (buf, dp, len)==0)
- break;
- fclose (f_out);
- }
-
-
-
-
- /*
- * copy from in to out, decoding as you go along.
- */
-
- #define DEC(c) (((c) - ' ') & 077)
-
- decode(in, out)
- FILE *in;
- FILE *out;
- {
- char buf[80];
- char *bp;
- int n;
-
- for (;;) {
- /* for each input line */
- if (fgets(buf, sizeof buf, in) == NULL)
- p_error (10, "Uudecode Short file\n", "");
-
- n = DEC(buf[0]);
- if (n <= 0)
- break;
- bp = &buf[1];
- while (n > 0) {
- outdec(bp, out, n);
- bp += 4;
- n -= 3;
- }
- }
- }
-
-
-
-
- /*
- * output a group of 3 bytes (4 input characters).
- * the input chars are pointed to by p, they are to
- * be output to file f. n is used to tell us not to
- * output all of them at the end of the file.
- */
-
- outdec(p, f, n)
- char *p;
- FILE *f;
- {
- int c1, c2, c3;
-
- c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
- c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
- c3 = DEC(p[2]) << 6 | DEC(p[3]);
- if (n >= 1)
- fputc(c1, f);
- if (n >= 2)
- fputc(c2, f);
- if (n >= 3)
- fputc(c3, f);
- }
-
-
-
-
- /*
- * DO_TEST () - do_test () tries to perform the test
- * requested by the shar script. At the moment the
- * following tests are recognized
- *
- * test ! -d directoryname
- * test -f filename
- * test <number> -ne wc ... do a word count of
- * the file
- */
-
- int do_test (fp)
- FILE *fp;
- {
- FILE *tfp;
-
- char flag [10], fname [100];
- int invert = FALSE;
- long wc_arg;
- get_tok (flag, fp);
- if (strcmp (flag, "!")==0) {
- invert = TRUE;
- get_tok (flag, fp);
- }
- if (strcmp (flag, "-f")==0) {
- get_tok (fname, fp);
- fix_file_name (fname);
- if (tfp=fopen (fname, "r"))
- fclose (tfp);
- }
- else if (strcmp (flag, "-d")==0) {
- get_tok (fname, fp);
- fix_file_name (fname);
- if (tfp=(FILE *) opendir (fname))
- closedir (tfp);
- }
- else if (isdigit(flag [0])) {
- wc_arg = atol (flag);
- get_tok (flag, fp);
- if (strcmp (flag, "-ne")==0) {
- get_tok (fname, fp);
- return ((w_cnt (fname, wc_arg)));
- }
- else {
- cmd_init ();
- return ((int) test_flag);
- }
- }
- else {
- cmd_init ();
- return ((int) test_flag);
- }
- return ((invert)?!(tfp):tfp);
- }
-
-
-
-
- /*
- * W_CNT () - This part of test is a separate function
- * 'cause I don't like to nest that deep. by the time
- * w_cnt () has been passed control it's broken down the
- * shar script command of the form
- * if test 488 -ne "`wc -c < 'FileName'`"
- * to
- * `wc -c < 'FileName'`
- * which is not too hard to extract the filename from
- */
-
- int w_cnt (name, arg)
- char *name;
- long arg;
- {
- char filename [65];
- struct stat statbuf;
- char *np, *index (), *rindex ();
- np = index (name, '\'') +1;
- *index (np, '\'') = '\0';
- strcpy (filename, np);
- fix_file_name (filename);
- stat (filename, &statbuf);
- if (statbuf.st_size != arg)
- return (1);
- return (0);
- }
-
-
-
-
- /*
- * DO_SKIP () - do_skip () passes thru the input until
- * he has determined that the command that would have
- * been processed at this point in the stream has been
- * flushed.
- */
-
- void do_skip (fp)
- FILE *fp;
- {
- char buf [256], delimiter [80], *dp;
- int len;
-
- do {
- get_tok (delimiter, fp);
- } while (strncmp (delimiter, "<<", 2));
- get_tok (delimiter, fp);
- dp = &delimiter [1];
- len = strlen (dp);
- while (fgets (buf, sizeof (buf), fp))
- if (strncmp (dp, buf, len)==0)
- break;
- cmd_init ();
- }
-
-
-
-
- /*
- * FIX_FILE_NAME () - does two things
- * (1) strips off any leading path identifiers
- * (2) appends the leading path header to the
- * filename presented to it.
- */
-
- void fix_file_name (s)
- char *s;
- {
- char buf [65], *tp, *rindex ();
- strcpy (buf, root_dir);
- if (tp=rindex (s, '/'))
- strcat (buf, tp+1);
- else
- strcat (buf, s);
- strcpy (s, buf);
- }
-